﻿using Android.App;
using Android.Content;
using Android.Content.Res;
using Android.Graphics;
using Android.Media;
using Android.Media.Session;
using Android.OS;
using Android.Runtime;
using Android.Support.V4.Media;
using Android.Support.V4.Media.Session;
using Android.Util;
using Android.Views;
using Android.Widget;
using AndroidX.Core.App;
using AndroidX.Media;
using AndroidX.Media.App;
using FantasticMusicPlayer;
using FantasticMusicPlayer.dbo.Model;
using Java.Interop;
using Java.Lang;
using NightPlayer.windows.utils;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using static NightPlayer.Resource;

namespace NightPlayer
{
    [Service(DirectBootAware = false, Enabled = true, Exported = true, Label = "播放服务", ForegroundServiceType = Android.Content.PM.ForegroundService.TypeMediaPlayback)]

    class PlayerService : Service 
    {
        const int SERVICE_ID = 100;
        const int NOTIFICATION_ID = 101;

        public const string BROADCAST_SONGCHANGED = "com.zyfdroid.nightplayer.SONG_CHANGED";
        public const string BROADCAST_COVERCHANGED = "com.zyfdroid.nightplayer.COVER_CHANGED";
        public const string BROADCAST_EXIT = "com.zyfdroid.nightplayer.EXIT";
        public const string BROADCAST_PLAYCHANGE = "com.zyfdroid.nightplayer.PLAYCHANGE";
        public const string BROADCAST_FAV_ON = "com.zyfdroid.nightplayer.FAV_ON";
        public const string BROADCAST_FAV_OFF = "com.zyfdroid.nightplayer.FAV_OFF";

        public const string NOTI_PLAY = "com.zyfdroid.nightplayer.noti.PLAY";
        public const string NOTI_PREV = "com.zyfdroid.nightplayer.noti.PREV";
        public const string NOTI_NEXT = "com.zyfdroid.nightplayer.noti.NEXT";
        public const string NOTI_EXIT = "com.zyfdroid.nightplayer.noti.EXIT";
        public const string NOTI_FAVO = "com.zyfdroid.nightplayer.noti.FAVO";

        public const string NOTI_VOLUP = "com.zyfdroid.nightplayer.noti.VOLUP";
        public const string NOTI_VOLDN = "com.zyfdroid.nightplayer.noti.VOLDN";
        public const string NOTI_NOISE = "com.zyfdroid.nightplayer.noti.NOISE";
        public const string NOTI_BBT = "com.zyfdroid.nightplayer.noti.BBT";
        public const string NOTI_PREVFOLDER = "com.zyfdroid.nightplayer.noti.PREVFOLDER";
        public const string NOTI_NEXTFOLDER = "com.zyfdroid.nightplayer.noti.NEXTFOLDER";


        public static IPlayListProvider playlist = null;
        public static PlayerController playerController = null;
        public static BassPlayerImpl player = null;
        public static string lastError = null;

        public static bool isFavChecked = false;

        private static VirtualDir favourite = null;

        PowerManager powerManager;
        PowerManager.WakeLock wakeLock;
        KeyguardManager keyguardManager;

        private NotificationManager notification;

        UDPMusicSwitcher UDPMusicSwitcher;


        public override void OnCreate()
        {
            base.OnCreate(); 

            powerManager = PowerManager.FromContext(this);
            wakeLock = powerManager.NewWakeLock(WakeLockFlags.Partial, "MusicPlayerWakelock");
            wakeLock.Acquire();
            notification = (NotificationManager)GetSystemService(Service.NotificationService);
            keyguardManager = (KeyguardManager)GetSystemService(Service.KeyguardService);
            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {
                NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "音乐通知栏", NotificationImportance.Low);
                channel.LockscreenVisibility = NotificationVisibility.Public;
                channel.EnableVibration(false);
                notification.CreateNotificationChannel(channel);
            }
            audioManager = (AudioManager)GetSystemService(Context.AudioService);

            

            favourite = ((CurrentDirectorySongProvider)playlist).GetFavList();
            
            playerController = new PlayerController(playlist);
            BassPlayerImpl player;
            player = new BassPlayerImpl();
            player.basePath = FilesDir.AbsolutePath;
            
            player.init();
            player.Looping = PrefPlayMode == 1;
            player.RaiseStop += Player_RaiseStop;
            player.CoverAvailable += Player_CoverAvailable;
            player.SongInfoAvailable += Player_SongInfoAvailable;
            player.TimerTick += Player_TimerTick;
            player.Stopped += Player_Stopped;
            player.Volume = 0.8f;
            playerController.SongChanged += PlayerController_SongChanged;
            player.PlaybackChanged += Player_PlaybackChanged1;
            PlayerService.player = player;

            playerController.ImReady();
            // player.Pause();
            player.Volume = PrefVolume;
            player.VolumeChannelBbt = PrefBbtVolume;
            player.VolumeChannelNoise = PrefNoiseVolume;
            player.DynamicRangeCompressed = PrefDRC;
            playerController.LoopMode = PrefPlayMode;
            playerController.Shuffe = PrefShuffe;
            player.BassBoost = PrefBass;

            
            mediasession = new MediaSessionCompat(this, "NightPlayer");

            mediasession.SetCallback(new MediaSessionCallback(this));
            mediasession.SetFlags((int)(MediaSessionFlags.HandlesMediaButtons | MediaSessionFlags.HandlesTransportControls));
            // 海信touch适配：需要仔细调整字段顺序来让系统获取到东西
            updatePlaybackState(false);
            mediasession.Active = true;
            notificationEventHandler = new NotificationEventHandler(this);

            IntentFilter inf = new IntentFilter();
            inf.AddAction(NOTI_NEXT);
            inf.AddAction(NOTI_PREV);
            inf.AddAction(NOTI_PLAY);
            inf.AddAction(NOTI_EXIT);
            inf.AddAction(NOTI_FAVO);

            inf.AddAction(NOTI_VOLDN);  
            inf.AddAction(NOTI_VOLUP);  
            inf.AddAction(NOTI_NOISE);  
            inf.AddAction(NOTI_BBT);  
            inf.AddAction(NOTI_PREVFOLDER);  
            inf.AddAction(NOTI_NEXTFOLDER); 
            
            
            if(Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {

                RegisterReceiver(notificationEventHandler, inf, ReceiverFlags.Exported);
            }
            else
            {

                RegisterReceiver(notificationEventHandler, inf);
            }

            player.PlaybackChanged += Player_PlaybackChanged;

            if (DateTime.Now.Hour >= 22 || DateTime.Now.Hour <= 5)
            {

                player.RemainMinute = PrefNightTimer;
                player.ScheduledStop = true;
            }

            int dsptype = PrefSrsWow;
            if (dsptype == 0)
            {
                ((DspSwitcher)player.SurroundSound).WrappedDSP = null;
            }
            if (dsptype == 1)
            {
                ((DspSwitcher)player.SurroundSound).WrappedDSP = new SurroundDSP();
            }
            if (dsptype == 2)
            {
                ((DspSwitcher)player.SurroundSound).WrappedDSP = new SpeakerInRoomDSP();
            }
            try
            {
                PlayerService.player.LoadFx(PrefMusicFx);
            }
            catch (System.Exception ex)
            {
            }
            if (Program.AppSettings.UDPMusicSwitch)
            {
                UDPMusicSwitcher = new UDPMusicSwitcher(this);
                UDPMusicSwitcher.start();
            }
        }


        // 双击音量键后台快速切歌
        private long lastVolumeDeltaed = -1;
        private int lastVolumeDirection = 0;
        private int lastVolume = 114514; // 初始值，不会真有人的手机有那么多段音量吧

        public static void onUserAction(Context ctx)
        {
            var remainTime = ctx.GetSharedPreferences(prefslot, FileCreationMode.Private).GetInt("nighttimer", 90);
            var volMusic = ctx.GetSharedPreferences(prefslot,FileCreationMode.Private).GetFloat("vol", 0.8f); 
            var volNoise = ctx.GetSharedPreferences(prefslot,FileCreationMode.Private).GetFloat("volnoise", 0.8f); 
            var volBBT = ctx.GetSharedPreferences(prefslot,FileCreationMode.Private).GetFloat("volbbt", 0.8f); 
            if(player == null)
            {
                return;
            }
            
            if (player.ScheduledStop && Program.AppSettings.SleepTimerAwareness)
            {
                var remainMinutes = player.RemainMinute;
                double passedMinute = remainTime - remainMinutes;
                var addMinute = (int)Java.Lang.Math.Ceil(passedMinute * (1d - 0.618d));
                if(addMinute <= 0) { addMinute = 1; }
                var newval = remainMinutes + addMinute;
                if(newval > remainTime) { newval = remainTime; }
                player.RemainMinute = newval;
            }
            player.Volume = volMusic;
            player.VolumeChannelNoise = volNoise;
            player.VolumeChannelBbt = volBBT;
        }


        private void Player_TimerTick(object sender, EventArgs e)
        {
            if (Program.AppSettings.UseLockscreenMusicSwitch)
            {
                int currentVolume = audioManager.GetStreamVolume(Android.Media.Stream.Music);
                if (currentVolume != lastVolume)
                {
                    if (powerManager == null)
                    {
                        return;
                    }
                    if (powerManager.IsInteractive) //当屏幕亮起的时候不触发切歌
                    {
                        lastVolume = currentVolume;
                        return;
                    }
                    if (iabs(currentVolume - lastVolume) == 2)
                    {

                        onVolumeDirection(currentVolume > lastVolume ? 1 : -1);
                        try
                        {
                            audioManager.SetStreamVolume(Android.Media.Stream.Music, lastVolume, VolumeNotificationFlags.RemoveSoundAndVibrate);
                            currentVolume = lastVolume;
                        }
                        catch { }

                    }
                    else if (iabs(currentVolume - lastVolume) == 1)
                    {
                        int currentDirection = currentVolume > lastVolume ? 1 : -1;
                        long currentTime = JavaSystem.CurrentTimeMillis();
                        if (currentTime - lastVolumeDeltaed < 1000 && lastVolumeDirection == currentDirection)
                        {
                            try
                            {
                                audioManager.SetStreamVolume(Android.Media.Stream.Music, currentVolume - currentDirection * 2, VolumeNotificationFlags.RemoveSoundAndVibrate);
                                currentVolume = currentVolume - currentDirection * 2;
                            }
                            catch { }
                            onVolumeDirection(currentDirection);
                            lastVolumeDeltaed = -1;
                        }
                        else
                        {
                            lastVolumeDirection = currentDirection;
                            lastVolumeDeltaed = currentTime;

                        }


                    }

                    lastVolume = currentVolume;
                }
            }
        }

        private void onVolumeDirection(int direction)
        {
            if(direction > 0)
            {
                onUserAction(this);
                playerController?.onPrevButtonClick();
            }
            else
            {
                onUserAction(this);
                playerController?.onNextButtonClick();
            }
        }

        private int iabs(int i) => i < 0 ? -i : i;

        string PrefMusicFx
        {
            get => SharedPreferences.GetString("musicfx", "");
            set => SharedPreferences.Edit().PutString("musicfx", value).Apply();
        }

        private void Player_PlaybackChanged1(object sender, EventArgs e)
        {
            if (player.IsPlaying && abandonPending == null) {
                gainAudioFocus();
            }
        }

        public void gainAudioFocus() {
            
            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {
                AudioFocusRequestClass req = new AudioFocusRequestClass.Builder(AudioFocus.Gain)
                    .SetAcceptsDelayedFocusGain(true)
                    .SetForceDucking(true)
                    .SetOnAudioFocusChangeListener(new MyAudioFocusChangedListener(this)).Build();
                abandonPending = req;
                audioManager.RequestAudioFocus(req);
            }
            else
            {
                MyAudioFocusChangedListener listener = new MyAudioFocusChangedListener(this);
                abandonPending = listener;
                AudioFocusRequest req = audioManager.RequestAudioFocus(listener, Android.Media.Stream.Music, AudioFocus.Gain);
            }
        }

        public void abandonAudioFocus()
        {
            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {
                if (abandonPending != null && abandonPending is AudioFocusRequestClass)
                {
                    audioManager.AbandonAudioFocusRequest((AudioFocusRequestClass)abandonPending);
                }
            }
            else
            {
                if (abandonPending != null && abandonPending is MyAudioFocusChangedListener)
                {
                    audioManager.AbandonAudioFocus((MyAudioFocusChangedListener)abandonPending);
                }
            }
            abandonPending = null;
        }

        private object abandonPending = null;

        class MyAudioFocusChangedListener : Java.Lang.Object, AudioManager.IOnAudioFocusChangeListener
        {
            bool lastPlaying = false;
            PlayerService _this;
            public MyAudioFocusChangedListener(PlayerService _this) {
                this._this = _this;
            }
        
            void AudioManager.IOnAudioFocusChangeListener.OnAudioFocusChange(AudioFocus focusChange)
            {
                if (player != null) {
                    if (focusChange == AudioFocus.Gain)
                    {
                        player.IsPlaying = lastPlaying;
                    }
                    else {
                        lastPlaying = player.IsPlaying;
                        player.Pause();
                        if (focusChange == AudioFocus.Loss) {
                            _this.abandonAudioFocus();
                        }
                    }
                }
            }

        }

        AudioManager audioManager;

        [return: GeneratedEnum]
        public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
        {
            StartForeground(SERVICE_ID, GetNotification());
            if(!intent.GetBooleanExtra("autoplay",false))
            {
                player?.Pause();
            }
            return StartCommandResult.Sticky;
        }

        NotificationEventHandler notificationEventHandler;

        private void Player_PlaybackChanged(object sender, EventArgs e)
        {
            updatePlaybackState(player.IsPlaying);
            SendBroadcast(new Intent(BROADCAST_PLAYCHANGE));
            updateNotification();
        }


        class MediaSessionCallback : Android.Support.V4.Media.Session.MediaSessionCompat.Callback {

            private PlayerService _access;
            public MediaSessionCallback(PlayerService ps)
            {
                _access = ps;
            }
                
            public override void OnPause()
            {

                BassPlayerImpl player = PlayerService.player;
                PlayerController controller = PlayerService.playerController;
                if (player == null) { return; }
                player.Pause();
            }

            public override void OnStop()
            {
                player.AquireRaiseStop();
            }

            public override void OnSeekTo(long pos)
            {
                player.CurrentPosition = pos;
            }

            public override void OnPlay()
            {

                BassPlayerImpl player = PlayerService.player;
                PlayerController controller = PlayerService.playerController;
                if (player == null) { return; }
                player.Play();
                PlayerService.onUserAction(_access);
            }

            public override void OnSkipToNext()
            {

                BassPlayerImpl player = PlayerService.player;
                PlayerController controller = PlayerService.playerController;
                if (player == null) { return; }
                controller.onNextButtonClick(); 
                PlayerService.onUserAction(_access);
            }
            public override void OnCustomAction(string action, Bundle? extras)
            {
                if (action == NOTI_EXIT)
                {

                    player.AquireRaiseStop();
                }
                if (action == NOTI_FAVO)
                {

                    toggleFavStatus();
                    _access.checkFavStatus();
                    _access.updateNotification();
                    if (isFavChecked)
                    {
                        _access.SendBroadcast(new Intent(BROADCAST_FAV_ON));
                    }
                    else
                    {
                        _access.SendBroadcast(new Intent(BROADCAST_FAV_OFF));
                    }
                    _access.updatePlaybackState(player.IsPlaying);
                }
            }
            public override void OnSkipToPrevious()
            {

                BassPlayerImpl player = PlayerService.player;
                PlayerController controller = PlayerService.playerController;
                if (player == null) { return; }
                controller.onPrevButtonClick();
                PlayerService.onUserAction(_access);
            }
        }

        class NotificationEventHandler : BroadcastReceiver
        {
            private PlayerService _access;
            public NotificationEventHandler(PlayerService _access) {
                this._access = _access;
            }
            public override void OnReceive(Context context, Intent intent)
            {

                BassPlayerImpl player = PlayerService.player;
                PlayerController controller = PlayerService.playerController;
                if (player == null) { return; }
                Console.WriteLine(intent.Action);
                switch (intent.Action) {
                    case NOTI_PLAY:
                        onUserAction(context);
                        player.PlayOrPause();
                        break;
                    case NOTI_PREV:
                        onUserAction(context);
                        controller.onPrevButtonClick();
                        break;
                    case NOTI_PREVFOLDER:

                        onUserAction(context);
                        controller.prevFolder();
                        break;
                    case NOTI_NEXTFOLDER:

                        onUserAction(context);
                        controller.nextFolder();
                        break;
                    case NOTI_VOLUP:
                    case NOTI_VOLDN:
                        int direction = intent.Action == NOTI_VOLUP ? 1 : -1;
                        var audioManager = (AudioManager)context.GetSystemService(Context.AudioService);
                        int currentVolume = audioManager.GetStreamVolume(Android.Media.Stream.Music) + direction;
                        int maxVolume = audioManager.GetStreamMaxVolume(Android.Media.Stream.Music);
                        int minVolume = audioManager.GetStreamMinVolume(Android.Media.Stream.Music);
                        if(currentVolume > maxVolume) { currentVolume = maxVolume; }
                        if(currentVolume < minVolume) { currentVolume = minVolume; }
                        audioManager.SetStreamVolume(Android.Media.Stream.Music, currentVolume, VolumeNotificationFlags.RemoveSoundAndVibrate);
                        break;
                    case NOTI_NEXT:
                        onUserAction(context);
                        controller.onNextButtonClick();
                        break;
                    case NOTI_EXIT:
                        player.AquireRaiseStop();
                        break;
                    case NOTI_NOISE:
                        var noisePath = context.GetSharedPreferences(PlayerService.prefslot, FileCreationMode.Private).GetString("lastnoise", "");
                        
                        if(player.ChannelNoiseType == 0)
                        {
                            player.ChannelNoiseType = noisePath.Length;
                            player.SetNoiseChannelNoise(noisePath);
                        }
                        else
                        {
                            player.ChannelNoiseType = 0;
                            player.SetNoiseChannelNoise(null);
                        }
                        break;
                    case NOTI_BBT:
                        var bbt = context.GetSharedPreferences(PlayerService.prefslot, FileCreationMode.Private).GetInt("lastbbt", -1);
                        Log.Debug("PlayerService","Last bbt = "+bbt);
                        if (bbt > 0) {
                            if (bbt < 0 || bbt >= MainActivity.BBTAdapter.bbtPath.Length)
                            {
                                return;
                            }
                            if(player.ChannelBbtType == 0)
                            {
                                player.ChannelBbtType = bbt;
                            }
                            else
                            {
                                player.ChannelBbtType = 0;
                            }
                            string realPath = AndroidIO.Path.Combine(context.FilesDir.AbsolutePath, LauncherActivity.AUDIODIR, MainActivity.BBTAdapter.bbtPath[player.ChannelBbtType]);

                            player.SetBbtChannelNoise(realPath);
                        }

                        break;
                    case NOTI_FAVO:
                        toggleFavStatus();
                        _access.checkFavStatus();
                        _access.updateNotification();
                        if (isFavChecked)
                        {
                            _access.SendBroadcast(new Intent(BROADCAST_FAV_ON));
                        }
                        else
                        {
                            _access.SendBroadcast(new Intent(BROADCAST_FAV_OFF));
                        }
                        break;
                }
            }
        }

        MediaSessionCompat mediasession;

        private void updatePlaybackState(bool isPlaying)
        {
            PlaybackStateCompat.Builder stateBuilder = new PlaybackStateCompat.Builder()
                    .SetActions(PlaybackStateCompat.ActionPlay
                            | PlaybackStateCompat.ActionPlayPause
                            | PlaybackStateCompat.ActionPause
                            | PlaybackStateCompat.ActionSeekTo
                            | PlaybackStateCompat.ActionStop
                            | PlaybackStateCompat.ActionSkipToNext
                            | PlaybackStateCompat.ActionSkipToPrevious);
            stateBuilder.AddCustomAction(new PlaybackStateCompat.CustomAction.Builder(NOTI_FAVO, "收藏", isFavChecked ? Resource.Drawable.heart_fill_compat : Resource.Drawable.heart_compat).Build());
            stateBuilder.AddCustomAction(new PlaybackStateCompat.CustomAction.Builder(NOTI_EXIT, "退出", Resource.Drawable.exit_compat).Build());
            if (isPlaying)
            {
                stateBuilder.SetState((int)PlaybackStateCode.Playing,
                            player.CurrentPosition,
                        1);
            }
            else
            {
                stateBuilder.SetState((int)PlaybackStateCode.Paused,
                        player.CurrentPosition,
                        1);
            }
            MediaMetadataCompat metadata = new MediaMetadataCompat.Builder()
                .PutLong(MediaMetadataCompat.MetadataKeyDuration, player.TotalPosition)
                .PutString(MediaMetadataCompat.MetadataKeyTitle, player.title)
                .PutString(MediaMetadataCompat.MetadataKeyArtist, player.artist)
                .PutBitmap(MediaMetadataCompat.MetadataKeyAlbumArt,player.cover ?? BitmapFactory.DecodeResource(Resources,Resource.Drawable.musicicon))
                .PutString(MediaMetadataCompat.MetadataKeyAlbum, player.album).Build()
                ;
                ;
            if(mediasession == null)
            {
                return;
            }
            mediasession.SetPlaybackState(stateBuilder.Build());
            mediasession.SetMetadata(metadata);
            // 海信touch锁屏不显示解决2：更新active字段来强制刷新数据
            mediasession.Active = isPlaying;
        }

        float PrefVolume {
            get => SharedPreferences.GetFloat("vol", 0.8f);
        }


        int PrefDRC
        {
            get => SharedPreferences.GetInt("drc2", 0);
        }

        float PrefBbtVolume
        {
            get => SharedPreferences.GetFloat("volbbt", 0.3f);
        }

        int PrefSrsWow
        {
            get => SharedPreferences.GetInt("dsp", 0);
            set => SharedPreferences.Edit().PutInt("dsp", value).Apply();
        }
        float PrefNoiseVolume
        {
            get => SharedPreferences.GetFloat("volnoise", 0.3f);
        }

        int PrefPlayMode {
            get => SharedPreferences.GetInt("playmode", 0);
            set => SharedPreferences.Edit().PutInt("playmode", value).Apply();
        }

        int PrefNightTimer
        {
            get => SharedPreferences.GetInt("nighttimer", 90);
            set => SharedPreferences.Edit().PutInt("nighttimer", value).Apply();
        }

        bool PrefShuffe {
            get => SharedPreferences.GetBoolean("shuffe", false);
            set => SharedPreferences.Edit().PutBoolean("shuffe", value).Apply();
        }

        bool PrefBass
        {
            get => SharedPreferences.GetBoolean("bass", false);
            set => SharedPreferences.Edit().PutBoolean("bass", value).Apply();
        }

        public static string prefslot = "default";
        ISharedPreferences SharedPreferences => GetSharedPreferences(prefslot, FileCreationMode.Private);

        private void Player_RaiseStop(object sender, EventArgs e)
        {
            playlist.saveProgress();
            PrefPlayMode = playerController.LoopMode;// PrefPlayMode;
            PrefShuffe = playerController.Shuffe;// PrefShuffe;
            PrefBass = player.BassBoost;// PrefBass;
            player?.Stop();
            mediasession.SetPlaybackState(new PlaybackStateCompat.Builder().SetState(PlaybackStateCompat.StateStopped, 0, 1).Build());
            mediasession.Release();
            mediasession.Active = false;
            Console.WriteLine("Player raise stop.");
            SendBroadcast(new Intent(BROADCAST_EXIT));
            StopForeground(true);
            StopSelf();
        }

        private void PlayerController_SongChanged(object sender, SongSwitchedEventArgs e)
        {
            player.TargetLUFS = playerController.CurrentList.GetBalancedLUFS();
            player.Load(e.CurrentSong);
            System.Threading.Thread.Sleep(20);
            player.Looping = playerController.LoopMode == 1;
            player.Play();
        }

        private void Player_Stopped(object sender, EventArgs e)
        {
            playerController.onSongStop();
        }

        private void Player_SongInfoAvailable(object sender, SongInfoEventArgs e)
        {
            player.hiresAudio = e.HiResAudio;
            player. title = e.title;
            player.artist = e.artist;
            player.album = e.album;
            Log.Warn("SongInfo", e.title + " - " + e.artist + " - " + e.album);
            checkFavStatus();
            SendBroadcast(new Intent(BROADCAST_SONGCHANGED));
            if (isFavChecked)
            {
                SendBroadcast(new Intent(BROADCAST_FAV_ON));
            }
            else
            {
                SendBroadcast(new Intent(BROADCAST_FAV_OFF));
            }
            updatePlaybackState(player.IsPlaying);
        }

        void checkFavStatus()
        {
            isFavChecked = favourite.Songs.Contains(playerController.CurrentPlaying);
        }

        static void toggleFavStatus() {
            Console.WriteLine("Toggle Fav Status");
            if (!isFavChecked)
            {
                List<SongEntry> refSongs = favourite.Songs;
                refSongs.Add(playerController.CurrentPlaying);
                favourite.save();
                
                if (playerController.PlayListProvider is CurrentDirectorySongProvider)
                {
                    ((CurrentDirectorySongProvider)playerController.PlayListProvider).UpdatePlaylist();
                }
            }
            else
            {
                List<SongEntry> refSongs = favourite.Songs;
                refSongs.Remove(playerController.CurrentPlaying);
                favourite.save();

                if (playerController.PlayListProvider is CurrentDirectorySongProvider)
                {
                    ((CurrentDirectorySongProvider)playerController.PlayListProvider).UpdatePlaylist();
                }
            }
        }


        private void Player_CoverAvailable(object sender, AlbumEventArgs e)
        {
            player.cover?.Dispose();
            player.cover = e.cover;
            SendBroadcast(new Intent(BROADCAST_COVERCHANGED));
            updateNotification();
        }

        const string NOTIFICATION_CHANNEL_ID = "nightplayer_notification";

        private Notification GetNotification() {
            

            Intent clickingIntent = new Intent(this,typeof(MainActivity));
            clickingIntent.AddFlags(ActivityFlags.NewTask | ActivityFlags.BroughtToFront);

            Android.Graphics.Bitmap cover = player.cover;

            if(cover != null)
            {
                int width = player.cover.Width;
                int height = player.cover.Height;
                int newWidth = 480;
                int newHeight = 480;
                float scaleWidth = ((float)newWidth) / (float)width;
                float scaleHeight = ((float)newHeight) / (float)height;
                Matrix matrix = new Matrix();
                matrix.PostScale(scaleWidth, scaleHeight);
                Android.Graphics.Bitmap newbm = Android.Graphics.Bitmap.CreateBitmap(player.cover, 0, 0, width, height, matrix, true); ;
                cover = newbm;

            }
            else
            {
                cover = Android.Graphics.BitmapFactory.DecodeResource(Resources, Resource.Drawable.musicicon);
            }


            AndroidX.Core.App.NotificationCompat.Builder nb = new AndroidX.Core.App.NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);

            bool isNewStyle = Build.VERSION.SdkInt >= BuildVersionCodes.Tiramisu;

            if (!isNewStyle)
            {
                nb = nb.AddAction(Resource.Drawable.prev, "上一曲", getActionIntent(NOTI_PREV));
                nb = nb.AddAction(player.IsPlaying ?  Resource.Drawable.pause : Resource.Drawable.play, "播放", getActionIntent(NOTI_PLAY));
                nb = nb.AddAction(Resource.Drawable.next, "下一曲", getActionIntent(NOTI_NEXT));
                nb = nb.AddAction(isFavChecked ? Resource.Drawable.heart_fill : Resource.Drawable.heart, "收藏", getActionIntent(NOTI_FAVO));
                nb = nb.AddAction(Resource.Drawable.exit, "退出", getActionIntent(NOTI_EXIT));
            }
            else
            {
                nb = nb.AddAction(isFavChecked ? Resource.Drawable.heart_fill_compat : Resource.Drawable.heart_compat, "收藏", getActionIntent(NOTI_FAVO));
                nb = nb.AddAction(Resource.Drawable.exit_compat, "退出", getActionIntent(NOTI_EXIT));
            }
            
            AndroidX.Media.App.NotificationCompat.MediaStyle mediaStyle = new AndroidX.Media.App.NotificationCompat.MediaStyle() ;
            if(mediasession != null)
            {
                mediaStyle.SetMediaSession(mediasession.SessionToken);
            }
            if (isNewStyle)
            {

                mediaStyle.SetShowActionsInCompactView(0, 1);
            }
            else
            {

                mediaStyle.SetShowActionsInCompactView(0, 1, 2, 3, 4);
            }

            mediaStyle.SetShowCancelButton(false);
            nb.SetSmallIcon(Resource.Drawable.playlist);
            nb.SetLargeIcon(cover);
            nb.SetContentTitle(player.title);
            nb.SetContentText(player.artist +" - "+player.album);

            nb.SetStyle(mediaStyle) ;
            nb.SetContentIntent(PendingIntent.GetActivity(this, 0, clickingIntent, PendingIntentFlags.Immutable));       
            return nb.Build();
        }

        PendingIntent getActionIntent(string action) {
            Intent i = new Intent(action);
            return PendingIntent.GetBroadcast(this, 101, i, PendingIntentFlags.Immutable);
        }

        void updateNotification() {
            NotificationManager nm = (NotificationManager)GetSystemService(Service.NotificationService);
            nm.Notify(SERVICE_ID, GetNotification());
        }

        public override IBinder OnBind(Intent intent)
        {
            return null;
        }

        public override void OnDestroy()
        {
            base.OnDestroy();

            Console.WriteLine("Ondestroy called.");
            if (mediasession != null)
            {
                mediasession.Active = false;
                mediasession.Dispose();
            }

            UDPMusicSwitcher?.Dispose();
            try
            {
                StopForeground(true);
            }
            catch { }
            UnregisterReceiver(notificationEventHandler);
            // 需要正确释放这玩意，否则使用自动播放功能时第二次不会生效
            abandonAudioFocus();
            wakeLock.Release();
            playlist = null;
            playerController = null;
            player.Dispose();
            player = null;
            prefslot = "default";
            favourite = null;

            Console.WriteLine("Ondestroy done.");
        }


    }
}